package srzy.driver

import srzy.socket._
import srzy.common.Common
import java.util.Formatter
import srzy.common.Logging
import scala.actors.Actor
import scala.actors.Actor._
import srzy.diameter._
import scala.xml.Node

object HbHId {
  var i = 2000L
  def apply() = {
    i += 1
    i
  }
}

object EtEId {
  var i = 2000L
  def apply() = {
    i += 1
    i
  }
}

abstract class DCCClientRece(getSocketConn: => srzy.socket.DCCSocketConn) extends Actor with Logging {

  var sc: srzy.socket.DCCSocketConn

  override def act = {
    while (true) {
      try {
        val arr = sc.read

        val node = try {
          arr.toDCCNode
        } catch {
          case ex: Exception => {
            logger.debug("rece :\n" + arr.toFormatStr)
            ex.printStackTrace()
            sys.exit
          }
        }
        val pp = new xml.PrettyPrinter(800, 2)

        node.attributes.apply("name").head.text match {
          case "DWR" => {
            val (hbhId, eteId) = srzy.diameter.getHbHIdAndEtEIdFromHead(arr)
            val llll = List(("HbH-id", hbhId), ("EtE-id", eteId))
            val DWAMsg = (<command name="DWA">
                            <avp name="Result-Code" value="2001"></avp>
                            <avp name="Origin-Host" value="tydic2.chinatelecom.com"></avp>
                            <avp name="Origin-Realm" value="chinatelecom.com"></avp>
                          </command>)
            val bytes = DWAMsg.toBytes(llll)
            //            logger.debug("send :\n" + bytes.toDCCCompareLog)
            sc.write(bytes)
            logger.info("DWR Msg")
          }
          case "NCR" => {
            logger.info("NCR Msg")
          }
          case "NCA" => {
            logger.info("NCA Msg")
          }
          case _ => {
            logger.debug("rece :\n" + arr.toFormatStr)
            logger.debug("rece :\n" + pp.format(arr.toDCCNode))
            DCCMsgDealer ! ('rece, node.toString)
          }
        }
      } catch {
        case sce: java.net.SocketTimeoutException => {}
        case sce: SocketClosedException => {
          sc.close
          println("socket closed normally ,reconnect start")
          sc = getSocketConn
        }
        case ex: Exception => {
          sc.close
          logger.debug("socket error ,reconnect start ", ex)
          sc = getSocketConn
        }
      }
    }
  }
}

class DCCClient extends Actor with Logging {

  val dccSocket = try {
    SocketConn.connect("172.168.1.216", 23411)
  } catch {
    case ex: Exception =>
      ex.printStackTrace()
      exit()
  }

  def getDCCSocketConn = new DCCSocketConn {
    val socket = dccSocket
    val outStream = socket.getOutputStream()
    val inStream = socket.getInputStream()
  }

  override def act = {

    import srzy.diameter._
    val socketConn = getDCCSocketConn

    logger.debug("Authentication start")
    val CERMsg = <command name="CER">
                   <avp name="Origin-Host" value="tydic2.chinatelecom.com"></avp>
                   <avp name="Origin-Realm" value="chinatelecom.com"></avp>
                   <avp name="Host-IP-Address" value="0x0001aca801d8"></avp>
                   <avp name="Vendor-Id" value="11"></avp>
                   <avp name="Product-Name" value="HP Cx Interface"></avp>
                   <avp name="Origin-State-Id" value="62"></avp>
                   <avp name="Supported-Vendor-Id" value="10415"></avp>
                   <avp name="Auth-Application-Id" value="4"></avp>
                   <avp name="Acct-Application-Id" value="0"></avp>
                   <avp name="Firmware-Revision" value="1"></avp>
                 </command>
    val llll = List(("HbH-id", HbHId()), ("EtE-id", EtEId()))
    val arr = CERMsg.toBytes(llll)
    //    logger.debug("send :\n" + arr.toFormatStr)
    //    logger.debug("send :\n" + arr.toDCCCompareLog)
    socketConn.write(arr)

    val arr2: Array[Byte] = socketConn.read
    //    logger.debug("rece :\n" + arr2.toFormatStr)
    //    logger.debug("rece :\n" + arr2.toDCCCompareLog)
    logger.info("Authentication success")

    DCCMsgDealer.start

    new DCCClientRece(getDCCSocketConn) {
      var sc = socketConn
    }.start

    loop {
      react {
        case node: Node => {
          val pp = new xml.PrettyPrinter(800, 2)
          val arr = node.toBytes
          //          logger.debug("rece :\n" + arr.toFormatStr)
          logger.debug("send :\n" + pp.format(node.toBytes.toDCCNode))
          socketConn.write(arr)
        }
        case _ => logger.debug("error ")
      }
    }

  }

}

object DCCClient {

  def main(args: Array[String]): Unit = {
    deal
  }

  def deal = {

    val a = new DCCClient
    a.start
    val text = xml.XML loadFile "1.xml"
    val ll = (text \ "traffic" \ "send" \ "command").toList
    ll.foreach(x => {
      a ! x
      (DCCMsgDealer !! 'getRece).apply
    })
  }

}